{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# set是一种无序、可变的集合，其中的元素是唯一的（不重复的）\n",
    "# frozenset是一种无序、不可变、唯一的集合\n",
    "s1 = {1, 2, 3, 4, 5}\n",
    "print(s1)  # 输出: {1, 2, 3, 4, 5}\n",
    "\n",
    "s2 = set([6,7,8,9,0])\n",
    "print(s2)  \n",
    "\n",
    "# 使用 add() 方法来向集合中添加单个元素，使用 update() 方法来添加多个元素\n",
    "my_set = {1, 2, 3}\n",
    "my_set.add(4)\n",
    "print(my_set)  # 输出: {1, 2, 3, 4}\n",
    "\n",
    "my_set.update([5, 6, 7])\n",
    "print(my_set)  # 输出: {1, 2, 3, 4, 5, 6, 7}\n",
    "\n",
    "# 使用 remove() 或 discard() 方法来删除集合中的元素。\n",
    "# 如果元素不存在 remove() 方法会抛出 KeyError 异常；而 discard() 方法不会抛出异常\n",
    "my_set = {1, 2, 3, 4, 5}\n",
    "my_set.remove(3)\n",
    "print(my_set)  # 输出: {1, 2, 4, 5}\n",
    "\n",
    "my_set.discard(6)\n",
    "print(my_set)  # 输出: {1, 2, 4, 5}\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 集合运算\n",
    "set1 = {1, 2, 3}\n",
    "set2 = {1, 2, 3, 4, 5, 6}\n",
    "\n",
    "# 并集 |\n",
    "union_set = set1.union(set2)\n",
    "print(union_set)  # 输出: {1, 2, 3, 4, 5}\n",
    "# 交集 &\n",
    "intersection_set = set1.intersection(set2)\n",
    "print(intersection_set)  # 输出: {3}\n",
    "# 差集 -\n",
    "difference_set = set1.difference(set2)\n",
    "print(difference_set)  # 输出: {1, 2}\n",
    "\n",
    "# 对称差集: 两个集合中不重复的元素的集合\n",
    "symmetric_difference_set = set1.symmetric_difference(set2)\n",
    "print(symmetric_difference_set)  # 输出: {4, 5, 6}\n",
    "\n",
    "# 或者使用运算符\n",
    "symmetric_difference_set = set1 ^ set2\n",
    "print(symmetric_difference_set)  # 输出: {4, 5, 6}\n",
    "\n",
    "# 子集和超集：可以使用 issubset() 方法或 <= 运算符来检查一个集合是否是另一个集合的子集。\n",
    "print(set1.issubset(set2))  # 输出: True\n",
    "print(set1 <= set2)  # 输出: True\n",
    "\n",
    "# 使用 issuperset() 方法或 >= 运算符来检查一个集合是否是另一个集合的超集\n",
    "print(set2.issuperset(set1))  # 输出: True\n",
    "print(set2 >= set1)  # 输出: True\n",
    "\n",
    "# 不相交集合\n",
    "print(set1.isdisjoint(set2))  # 输出: False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "defaultdict(<class 'list'>, {'a': [1, 2], 'b': [4]})\n",
      "defaultdict(<class 'set'>, {'a': {1, 2}, 'b': {4}})\n"
     ]
    }
   ],
   "source": [
    "# 字典中的键映射多个值\n",
    "from collections import defaultdict\n",
    "# 使用 defaultdict 类来创建一个具有默认值的字典。\n",
    "# 默认值可以是任意类型，当访问不存在的键时，会返回默认值而不是抛出异常。\n",
    "\n",
    "d = defaultdict(list)\n",
    "d['a'].append(1)\n",
    "d['a'].append(2)\n",
    "d['b'].append(4)\n",
    "print(d)\n",
    "d = defaultdict(set)\n",
    "d['a'].add(1)\n",
    "d['a'].add(2)\n",
    "d['a'].add(2)\n",
    "d['b'].add(4)\n",
    "print(d)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "foo 1\n",
      "bar 2\n",
      "spam 6\n",
      "grok 4\n"
     ]
    }
   ],
   "source": [
    "# 保持元素被插入时的顺序\n",
    "from collections import OrderedDict\n",
    "\n",
    "d = OrderedDict()\n",
    "d['foo'] = 1\n",
    "d['bar'] = 2\n",
    "d['spam'] = 3\n",
    "d['grok'] = 4\n",
    "# Outputs \"foo 1\", \"bar 2\", \"spam 3\", \"grok 4\"\n",
    "for key in d:\n",
    "    print(key, d[key])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(10.75, 'FB') (612.78, 'AAPM')\n"
     ]
    }
   ],
   "source": [
    "# 字典的比较\n",
    "\n",
    "prices = {\n",
    "    'ACME': 45.23,\n",
    "    'AAPL': 612.78,\n",
    "    'AAPM': 612.78,\n",
    "    'IBM': 205.55,\n",
    "    'HPQ': 37.20,\n",
    "    'FB': 10.75\n",
    "}\n",
    "# 下面反转KV 先比较值再比较键\n",
    "min_price = min(zip(prices.values(), prices.keys()))\n",
    "max_price = max(zip(prices.values(), prices.keys()))\n",
    "print(min_price,max_price)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'y', 'x'}\n",
      "{'z'}\n",
      "{('y', 2)}\n",
      "<class 'dict_items'>\n",
      "{'y': 2, 'x': 1}\n"
     ]
    }
   ],
   "source": [
    "# 在两个字典中寻寻找相同点（比如相同的键、相同的值等）\n",
    "# 字典：键值对的集合\n",
    "a = {\n",
    "    'x' : 1,\n",
    "    'y' : 2,\n",
    "    'z' : 3\n",
    "}\n",
    "\n",
    "b = {\n",
    "    'w' : 10,\n",
    "    'x' : 11,\n",
    "    'y' : 2\n",
    "}\n",
    "# Find keys in common\n",
    "print(a.keys() & b.keys()) # { 'x', 'y' }\n",
    "\n",
    "# Find keys in a that are not in b\n",
    "print(a.keys() - b.keys()) # { 'z' }\n",
    "\n",
    "# Find (key,value) pairs in common\n",
    "print(a.items() & b.items()) # { ('y', 2) }\n",
    "\n",
    "print(type(a.items()))\n",
    "\n",
    "# Make a new dictionary with certain keys removed\n",
    "c = {key:a[key] for key in a.keys() - {'z', 'w'}}\n",
    "# c is {'x': 1, 'y': 2}\n",
    "print(c)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 5, 2, 9, 10]\n",
      "[{'x': 1, 'y': 2}, {'x': 1, 'y': 3}, {'x': 2, 'y': 4}]\n"
     ]
    }
   ],
   "source": [
    "# 在一个序列上面保持元素顺序的同时消除重复的值\n",
    "def dedupe(items):\n",
    "    seen = set()\n",
    "    for item in items:\n",
    "        if item not in seen:\n",
    "            yield item\n",
    "            seen.add(item)\n",
    "\n",
    "\n",
    "def dedupe(items, key=None):\n",
    "    seen = set()\n",
    "    for item in items:\n",
    "        val = item if key is None else key(item)\n",
    "        if val not in seen:\n",
    "            yield item\n",
    "            seen.add(val)\n",
    "\n",
    "\n",
    "a = [1, 5, 2, 1, 9, 1, 5, 10]\n",
    "d = [ {'x':1, 'y':2}, {'x':1, 'y':3}, {'x':1, 'y':2}, {'x':2, 'y':4}]\n",
    "\n",
    "\n",
    "print(list(dedupe(a)))\n",
    "print(list(dedupe(d, key=lambda d: (d['x'],d['y']))))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "51325.0\n",
      "51325.0\n",
      "slice(20, 23, None)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(10, 10, 1)"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 命名切片\n",
    "record = '....................100 .......513.25 ..........'\n",
    "cost = int(record[20:23]) * float(record[31:37])\n",
    "print(cost)\n",
    "\n",
    "# 不如\n",
    "SHARES = slice(20, 23)  # 创建了一个切片对象\n",
    "PRICE = slice(31, 37) # __start, __stop, __step\n",
    "cost = int(record[SHARES]) * float(record[PRICE])\n",
    "print(cost)\n",
    "print(SHARES)\n",
    "\n",
    "# 通过调用切片的 indices(size) 方法将它映射到一个已知大小的序列上。\n",
    "#  这个方法返回一个三元组 (start, stop, step) ，所有的值都会被缩小，直到适合这个已知序列的边界为止。 \n",
    "s = 'HelloWorld'\n",
    "PRICE.indices(len(s))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[('eyes', 8), ('the', 5), ('look', 4)]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'look': 4,\n",
       " 'into': 3,\n",
       " 'my': 3,\n",
       " 'eyes': 8,\n",
       " 'the': 5,\n",
       " 'not': 1,\n",
       " 'around': 2,\n",
       " \"don't\": 1,\n",
       " \"you're\": 1,\n",
       " 'under': 1}"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 找出一个序列中出现次数最多的元素\n",
    "from collections import Counter\n",
    "words = [\n",
    "    'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes',\n",
    "    'the', 'eyes', 'the', 'eyes', 'the', 'eyes', 'not', 'around', 'the',\n",
    "    'eyes', \"don't\", 'look', 'around', 'the', 'eyes', 'look', 'into',\n",
    "    'my', 'eyes', \"you're\", 'under'\n",
    "]\n",
    "word_counts = Counter(words)\n",
    "# 出现频率最高的3个单词\n",
    "top_three = word_counts.most_common(3)\n",
    "print(top_three)\n",
    "# Outputs [('eyes', 8), ('the', 5), ('look', 4)]\n",
    "d = dict()\n",
    "for i in words:\n",
    "    # 设置默认值。键存在，则返回对应的值；键不存在，添加键和默认值到字典中，返回默认值\n",
    "    d[i] = d.setdefault(i, 0)+1\n",
    "    # 也可以使用 get() 方法来获取字典中指定键的值，如果键不存在，则返回指定的默认值。 my_dict.get(key, default_value)。\n",
    "d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'dict'>\n",
      "None\n",
      "False\n",
      "dict_keys(['key2'])\n",
      "dict_values(['value2'])\n",
      "dict_items([('key2', 'value2')])\n",
      "{'key2': 'value2'}\n",
      "1\n",
      "{'key2': 'v2'}\n",
      "['key', 'key2']\n",
      "[('key', 'v3'), ('key2', 'v2')]\n"
     ]
    }
   ],
   "source": [
    "# dict\n",
    "my_dict={}\n",
    "print(type(my_dict))\n",
    "\n",
    "# 访问字典的值：如果键不存，可以使用 get() 方法来避免抛出 KeyError 异常。\n",
    "\n",
    "print(my_dict.get('key')) # None\n",
    "\n",
    "# 添加或更新字典的键值对：使用赋值语句来添加或更新字典中的键值对，例如 \n",
    "my_dict['key'] = 'value'\n",
    "my_dict['key2'] = 'value2'\n",
    "\n",
    "# 删除字典的键值对：使用 del 关键字来删除字典中的键值对，例如 \n",
    "del my_dict['key']\n",
    "\n",
    "# 检查键是否存在：使用 in 关键字来检查键是否存在于字典中，例如 \n",
    "print(key in my_dict)\n",
    "\n",
    "# 获取字典的键、值或键值对：使用 keys()、values() 和 items() 方法来获取字典的键、值或键值对的视图。你可以将这些视图转换为列表或迭代它们。\n",
    "print(my_dict.keys())\n",
    "print(my_dict.values())\n",
    "print(my_dict.items())\n",
    "\n",
    "# 使用字典推导式：字典推导式是一种快速创建字典的方法。它类似于列表推导式，但使用大括号 {} 来表示字典。\n",
    "d={key: value for key, value in my_dict.items()}\n",
    "print(d)\n",
    "\n",
    "# 获取字典的长度：使用 len() 函数来获取字典中键值对的数量\n",
    "print(len(my_dict))\n",
    "\n",
    "# 清空字典：使用 clear() 方法来清空字典\n",
    "my_dict.clear()\n",
    "\n",
    "# 复制字典：使用 copy() 方法来复制字典\n",
    "new_dict = my_dict.copy()\n",
    "\n",
    "# 合并字典：使用 update() 方法来合并字典，例如 \n",
    "# 这将把 other_dict 中的键值对添加到 my_dict 中，如果有相同的键，则会更新对应的值。\n",
    "d['key2']='v2' \n",
    "my_dict.update(d)\n",
    "print(my_dict)\n",
    "\n",
    "# 字典本身是无序的，但你可以使用 sorted() 函数对字典的键进行排序，并返回一个排序后的列表。\n",
    "my_dict['key']='v3' \n",
    "print(sorted(my_dict))\n",
    "print(sorted(my_dict.items()))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[{'fname': 'Big', 'lname': 'Jones', 'uid': 1004}, {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}, {'fname': 'David', 'lname': 'Beazley', 'uid': 1002}, {'fname': 'John', 'lname': 'Cleese', 'uid': 1001}]\n",
      "[{'fname': 'John', 'lname': 'Cleese', 'uid': 1001}, {'fname': 'David', 'lname': 'Beazley', 'uid': 1002}, {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}, {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}]\n",
      "[{'fname': 'Big', 'lname': 'Jones', 'uid': 1004}, {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}, {'fname': 'David', 'lname': 'Beazley', 'uid': 1002}, {'fname': 'John', 'lname': 'Cleese', 'uid': 1001}]\n",
      "[{'fname': 'John', 'lname': 'Cleese', 'uid': 1001}, {'fname': 'David', 'lname': 'Beazley', 'uid': 1002}, {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}, {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}]\n"
     ]
    }
   ],
   "source": [
    "# 根据某个或某几个字典字段来排序这个列表\n",
    "from operator import itemgetter\n",
    "\n",
    "rows = [\n",
    "    {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},\n",
    "    {'fname': 'David', 'lname': 'Beazley', 'uid': 1002},\n",
    "    {'fname': 'John', 'lname': 'Cleese', 'uid': 1001},\n",
    "    {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}\n",
    "]\n",
    "\n",
    "# itemgetter用于获取对象的某个属性或索引的值\n",
    "rows_by_fname = sorted(rows, key=itemgetter('fname'))\n",
    "rows_by_uid = sorted(rows, key=itemgetter('uid'))\n",
    "print(rows_by_fname)\n",
    "print(rows_by_uid)\n",
    "\n",
    "rows_by_fname = sorted(rows, key=lambda r: r['fname'])\n",
    "rows_by_lfname = sorted(rows, key=lambda r: (r['lname'],r['fname']))\n",
    "print(rows_by_fname)\n",
    "print(rows_by_uid)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[User(23), User(3), User(99)]\n",
      "[User(3), User(23), User(99)]\n",
      "[User(3), User(23), User(99)]\n"
     ]
    }
   ],
   "source": [
    "# 对不支持原生比较的对象排序\n",
    "class User:\n",
    "    def __init__(self, user_id):\n",
    "        self.user_id = user_id\n",
    "\n",
    "    def __repr__(self):\n",
    "        return 'User({})'.format(self.user_id)\n",
    "from operator import attrgetter\n",
    "\n",
    "users = [User(23), User(3), User(99)]\n",
    "print(users)\n",
    "print(sorted(users, key=lambda u: u.user_id))\n",
    "# attrgetter 用于获取对象的属性值而不是索引值\n",
    "print(sorted(users,key=attrgetter('user_id')))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "07/01/2012\n",
      "  {'address': '5412 N CLARK', 'date': '07/01/2012'}\n",
      "  {'address': '4801 N BROADWAY', 'date': '07/01/2012'}\n",
      "07/02/2012\n",
      "  {'address': '5800 E 58TH', 'date': '07/02/2012'}\n",
      "  {'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'}\n",
      "  {'address': '1060 W ADDISON', 'date': '07/02/2012'}\n",
      "07/03/2012\n",
      "  {'address': '2122 N CLARK', 'date': '07/03/2012'}\n",
      "07/04/2012\n",
      "  {'address': '5148 N CLARK', 'date': '07/04/2012'}\n",
      "  {'address': '1039 W GRANVILLE', 'date': '07/04/2012'}\n",
      "07/01/2012 [{'address': '5412 N CLARK', 'date': '07/01/2012'}, {'address': '4801 N BROADWAY', 'date': '07/01/2012'}]\n",
      "07/02/2012 [{'address': '5800 E 58TH', 'date': '07/02/2012'}, {'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'}, {'address': '1060 W ADDISON', 'date': '07/02/2012'}]\n",
      "07/03/2012 [{'address': '2122 N CLARK', 'date': '07/03/2012'}]\n",
      "07/04/2012 [{'address': '5148 N CLARK', 'date': '07/04/2012'}, {'address': '1039 W GRANVILLE', 'date': '07/04/2012'}]\n"
     ]
    }
   ],
   "source": [
    "# 通过某个字段将记录分组\n",
    "from collections import defaultdict\n",
    "from itertools import groupby\n",
    "from operator import itemgetter\n",
    "rows = [\n",
    "    {'address': '5412 N CLARK', 'date': '07/01/2012'},\n",
    "    {'address': '5148 N CLARK', 'date': '07/04/2012'},\n",
    "    {'address': '5800 E 58TH', 'date': '07/02/2012'},\n",
    "    {'address': '2122 N CLARK', 'date': '07/03/2012'},\n",
    "    {'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'},\n",
    "    {'address': '1060 W ADDISON', 'date': '07/02/2012'},\n",
    "    {'address': '4801 N BROADWAY', 'date': '07/01/2012'},\n",
    "    {'address': '1039 W GRANVILLE', 'date': '07/04/2012'},\n",
    "]\n",
    "\n",
    "# Sort by the desired field first\n",
    "rows.sort(key=itemgetter('date'))\n",
    "# groupby() 函数扫描整个序列并且查找连续相同值（或者根据指定 key 函数返回值相同）的元素序列。\n",
    "# 在每次迭代的时候，它会返回一个值和一个迭代器对象，\n",
    "# 这个迭代器对象可以生成元素值全部等于上面那个值的组中所有对象。\n",
    "for date, items in groupby(rows, key=itemgetter('date')):\n",
    "    print(date)\n",
    "    for i in items:\n",
    "        print(' ', i)\n",
    "\n",
    "# 想根据 date 字段将数据分组到一个大的数据结构中去，并且允许随机访问\n",
    "rows_by_date = defaultdict(list)\n",
    "for row in rows:\n",
    "    rows_by_date[row['date']].append(row)\n",
    "for i,j in rows_by_date.items():\n",
    "    print(i,j)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 4, 10, 2, 3]\n",
      "<generator object <genexpr> at 0x7f030c27b920>\n",
      "['1', '2', '-3', '4', '5']\n",
      "[1, 4, 0, 10, 0, 2, 3, 0]\n",
      "[0, 0, -5, 0, -7, 0, 0, -1]\n",
      "['5800 E 58TH', '1060 W ADDISON', '4801 N BROADWAY']\n"
     ]
    }
   ],
   "source": [
    "# 过滤序列元素\n",
    "from itertools import compress\n",
    "mylist = [1, 4, -5, 10, -7, 2, 3, -1]\n",
    "res = [n for n in mylist if n > 0]\n",
    "print(res)\n",
    "\n",
    "# 使用列表推导的一个潜在缺陷就是如果输入非常大的时候会产生一个非常大的结果集，占用大量内存。\n",
    "# 如果你对内存比较敏感，那么你可以使用生成器表达式迭代产生过滤的元素\n",
    "pos = (n for n in mylist if n > 0)\n",
    "print(pos)\n",
    "\n",
    "# 过滤规则比较复杂，不能简单的在列表推导或者生成器表达式中表达出来\n",
    "values = ['1', '2', '-3', '-', '4', 'N/A', '5']\n",
    "\n",
    "\n",
    "def is_int(val):\n",
    "    try:\n",
    "        x = int(val)\n",
    "        return True\n",
    "    except ValueError:\n",
    "        return False\n",
    "\n",
    "\n",
    "ivals = list(filter(is_int, values))\n",
    "print(ivals)\n",
    "\n",
    "# 过滤操作的一个变种就是将不符合条件的值用新的值代替，而不是丢弃它们\n",
    "clip_neg = [n if n > 0 else 0 for n in mylist]\n",
    "print(clip_neg)\n",
    "clip_pos = [n if n < 0 else 0 for n in mylist]\n",
    "print(clip_pos)\n",
    "\n",
    "# 先创建一个 Boolean 序列，指示哪些元素符合条件。 然后 compress() 函数(返回迭代器)根据这个序列去选择输出对应位置为 True 的元素\n",
    "addresses = [\n",
    "    '5412 N CLARK',\n",
    "    '5148 N CLARK',\n",
    "    '5800 E 58TH',\n",
    "    '2122 N CLARK',\n",
    "    '5645 N RAVENSWOOD',\n",
    "    '1060 W ADDISON',\n",
    "    '4801 N BROADWAY',\n",
    "    '1039 W GRANVILLE',\n",
    "]\n",
    "counts = [0, 3, 10, 4, 1, 7, 6, 1]\n",
    "more5 = [n > 5 for n in counts]\n",
    "print(list(compress(addresses, more5)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'AAPL': 612.78, 'IBM': 205.55}\n",
      "{'AAPL': 612.78, 'IBM': 205.55, 'HPQ': 37.2}\n"
     ]
    }
   ],
   "source": [
    "# 构造一个字典，它是另外一个字典的子集\n",
    "prices = {\n",
    "    'ACME': 45.23,\n",
    "    'AAPL': 612.78,\n",
    "    'IBM': 205.55,\n",
    "    'HPQ': 37.20,\n",
    "    'FB': 10.75\n",
    "}\n",
    "# Make a dictionary of all prices over 200\n",
    "p1 = {key: value for key, value in prices.items() if value > 200}\n",
    "print(p1)\n",
    "\n",
    "# Make a dictionary of tech stocks\n",
    "tech_names = {'AAPL', 'IBM', 'HPQ', 'MSFT'}\n",
    "p2 = {key: value for key, value in prices.items() if key in tech_names}\n",
    "print(p2)\n",
    "p2 = {key: prices[key] for key in prices.keys() & tech_names} # 更慢\n",
    "print(p2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "55\n"
     ]
    }
   ],
   "source": [
    "# 转换并同时计算数据\n",
    "nums = [1, 2, 3, 4, 5]\n",
    "s = sum(x * x for x in nums)\n",
    "print(s)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "5\n"
     ]
    }
   ],
   "source": [
    "# (从逻辑上)合并多个字典或映射\n",
    "from collections import ChainMap\n",
    "# 在内部创建了一个容纳这些字典的列表 并重新定义了一些常见的字典操作来遍历这个列表\n",
    "\n",
    "a = {'x': 1, 'z': 3}\n",
    "b = {'y': 2, 'z': 4}\n",
    "c = ChainMap(a, b)\n",
    "print(c['x'])  # Outputs 1 (from a)\n",
    "print(c['y'])  # Outputs 2 (from b)\n",
    "# 如果出现重复键，那么第一次出现的映射值会被返回\n",
    "print(c['z'])  # Outputs 3 (from a)\n",
    "\n",
    "# 如果原字典做了更新，这种改变会反应到新的合并字典中去\n",
    "a['z']=5\n",
    "print(c['z'])\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "qwenv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.3"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
